<?php

declare(strict_types=1);

namespace app\common\controller;

use think\App;
use think\exception\ValidateException;
use think\response\Json;
use think\facade\Log;
use think\facade\Db;
use think\facade\Request;
use app\common\model\order\ShipOrder;
use app\common\service\third_party_api\ShipApiService;
use app\common\service\third_party_api\SMSService;
use app\common\service\third_party_api\PayApiService;

/**
 * 船票接口回调控制器
 * 负责接收船票接口的异步回调通知，处理订单状态更新、票务信息变更等
 */
class ShipApiCallback
{
    /**
     * 应用实例
     * @var App
     */
    protected $app;

    /**
     * 船票API服务实例
     * @var ShipApiService
     */
    protected $shipApiService;

    /**
     * 支付API服务实例
     * @var PayApiService
     */
    protected $payApiService;

    /**
     * 构造函数
     * @param App $app 应用实例
     * @param ShipApiService $shipApiService 船票API服务实例
     * @param PayApiService $payApiService 支付API服务实例
     */
    public function __construct(App $app, ShipApiService $shipApiService, PayApiService $payApiService)
    {
        $this->app = $app;
        $this->shipApiService = $shipApiService;
        $this->payApiService = $payApiService;
    }

    /**
     * 船票订单状态回调处理
     * 用于接收船票订单状态变更的通知
     * @return Json
     */
    public function orderStatusNotify()
    {
        try {
            // 获取回调数据
            $data = Request::param();

            // 记录回调日志
            Log::info('船票订单状态回调通知: ' . json_encode($data));

            // 验证必要参数
            if (!isset($data['OrderNo']) || empty($data['OrderNo'])) {
                Log::error('船票订单回调缺少订单号');
                return json([
                    'State' => 0,
                    'Message' => '缺少订单号',
                ]);
            }

            // 获取订单模型
            $shipOrderModel = new ShipOrder();

            // 查询订单
            $shipOrder = $shipOrderModel->where('self_order_no', $data['OrderNo'])->find();

            if (!$shipOrder) {
                Log::error('船票订单不存在: ' . $data['OrderNo']);
                return json([
                    'State' => 0,
                    'Message' => '订单不存在',
                ]);
            }

            // 保存原始回调数据
            $shipOrderModel->where('self_order_no', $data['OrderNo'])->update([
                'tc_notify_data' => json_encode($data),
                'update_time' => time(),
            ]);

            // 处理订单状态更新
            $this->processOrderStatusUpdate($shipOrder, $data);

            // 返回成功响应
            return json([
                'State' => 1,
                'Message' => 'Success',
            ]);
        } catch (ValidateException $e) {
            // 记录验证异常日志
            Log::error('船票订单状态回调验证失败: ' . $e->getMessage());
            return json([
                'State' => 0,
                'Message' => $e->getMessage(),
            ]);
        } catch (\Exception $e) {
            // 记录系统异常日志
            Log::error('船票订单状态回调处理异常: ' . $e->getMessage());
            return json([
                'State' => 0,
                'Message' => '系统异常',
            ]);
        }
    }

    /**
     * 船票出票结果回调处理
     * 用于接收船票出票结果的通知
     * @return Json
     */
    public function ticketResultNotify()
    {
        $result = [];
        try {
            // 获取回调数据
            $data = Request::param();

            // 记录回调日志
            Log::info('船票出票结果回调通知: ' . json_encode($data));

            // 验证必要参数
            if (!isset($data['OrderNo']) || empty($data['OrderNo']) || !isset($data['TicketStatus'])) {
                Log::error('船票出票回调缺少必要参数');
                return json([
                    'State' => 1,
                    'Message' => 'Success',
                ]);
            }

            // 获取订单模型
            $shipOrderModel = new ShipOrder();

            // 查询订单
            $shipOrder = $shipOrderModel->where('self_order_no', $data['OrderNo'])->find();

            if (!$shipOrder) {
                Log::error('船票订单不存在: ' . $data['OrderNo']);
                return json([
                    'State' => 1,
                    'Message' => 'Success',
                ]);
            }

            // 解密JSON字段
            $shipOrder['contact_list'] = json_decode($shipOrder['contact_list'], true);
            $shipOrder['chooseSeat'] = json_decode($shipOrder['chooseSeat'], true);
            $shipOrder['chooseFlight'] = json_decode($shipOrder['chooseFlight'], true);
            $shipOrder['shipline'] = json_decode($shipOrder['shipline'], true);

            // 保存出票结果回调数据
            $updateData = [
                'tc_ticket_notify' => json_encode($data),
                'update_time' => time(),
            ];

            // 根据出票状态更新订单
            switch ($data['TicketStatus']) {
                case 'SUCCESS':
                    // 出票成功
                    $updateData['status'] = 3;  // 出票成功状态
                    $updateData['GetTicketNOResult'] = 1;

                    // 如果回调中包含票务信息，保存票务信息
                    if (isset($data['Tickets'])) {
                        $updateData['tickets_info'] = json_encode($data['Tickets']);
                    }

                    Log::info('船票订单出票成功: ' . $data['OrderNo']);

                    // 更新订单
                    $shipOrderModel->where('id', $shipOrder['id'])->update($updateData);

                    // 发送短信通知（如果需要）
                    if ($shipOrder['need_sms']) {
                        $smsService = new SMSService();
                        $smsService->send($shipOrder['booking_tel'], $shipOrder['tc_order_no']);
                    }
                    break;
                case 'FAILED':
                    // 出票失败
                    $updateData['status'] = 10;  // 出票失败状态
                    $updateData['GetTicketNOResult'] = 0;

                    // 记录失败原因
                    if (isset($data['FailReason'])) {
                        $updateData['fail_reason'] = $data['FailReason'];
                    }

                    Log::info('船票订单出票失败: ' . $data['OrderNo']);

                    // 更新订单
                    $shipOrderModel->where('id', $shipOrder['id'])->update($updateData);

                    // 重新查询订单，获取最新状态
                    $shiporder = $shipOrderModel->where('self_order_no', $data['OrderNo'])->find();

                    // 如果订单未退款，进行自动退款
                    if ($shiporder['refund_money'] <= 0) {
                        $this->processAutoRefund($shiporder);
                    }
                    break;
                case 'PROCESSING':
                    // 出票处理中
                    $updateData['status'] = 2;  // 出票处理中状态
                    Log::info('船票订单出票处理中: ' . $data['OrderNo']);

                    // 更新订单
                    $shipOrderModel->where('id', $shipOrder['id'])->update($updateData);
                    break;
            }

            // 返回成功响应
            return json([
                'State' => 1,
                'Message' => 'Success',
            ]);
        } catch (\Exception $e) {
            // 记录异常日志
            Log::error('船票出票结果回调处理异常: ' . $e->getMessage());
            // 记录调试信息到日志表（使用app_config表临时存储调试信息）
            Db::name('app_config')->insert([
                'name' => 'debug_log',
                'value' => json_encode(['time' => date('Y-m-d H:i:s'), 'message' => 'ticketResultNotify-Exception:' . $e->getMessage(), 'url' => Request::url(), 'params' => Request::param()]),
                'type' => 'debug',
                'title' => '调试日志',
                'create_time' => time()
            ]);
            return json([
                'State' => 1,
                'Message' => 'Success',
            ]);
        } catch (\Error $e) {
            // 记录错误日志
            Log::error('船票出票结果回调处理错误: ' . $e->getMessage());
            // 记录调试信息到日志表（使用app_config表临时存储调试信息）
            Db::name('app_config')->insert([
                'name' => 'debug_log',
                'value' => json_encode(['time' => date('Y-m-d H:i:s'), 'message' => 'ticketResultNotify-Error:' . $e->getMessage(), 'url' => Request::url(), 'params' => Request::param()]),
                'type' => 'debug',
                'title' => '调试日志',
                'create_time' => time()
            ]);
            return json([
                'State' => 1,
                'Message' => 'Success',
            ]);
        }
    }

    /**
     * 处理自动退款
     * @param array $shiporder 船票订单数据
     */
    protected function processAutoRefund(array $shiporder)
    {
        $selft_refund_no = uniqid();
        $refund_money = $shiporder['notify_pay_money'];

        // 特殊用户处理
        if ($shiporder['user_id'] . '' === '4224') {
            $refund_money = 0.04;
        }

        $result = [];

        // 根据支付方式进行退款
        if ($shiporder['pay_type'] == 1) {
            // 微信支付退款
            $result = $this->payApiService->wxRefund([
                'out_trade_no' => $shiporder['notify_data']['transaction_id'],
                'out_refund_no' => $selft_refund_no,
                'total_fee' => $shiporder['notify_data']['total_fee'],
                'refund_fee' => $refund_money * 100,
            ]);

            if (isset($result['result_code']) && $result['result_code'] == 'SUCCESS') {
                // 退款成功
                $this->updateRefundStatus($shiporder, $selft_refund_no, $refund_money, $result);
            } else {
                // 退款失败，记录响应信息
                $this->recordRefundFailure($shiporder, $result);
            }
        } elseif ($shiporder['pay_type'] == 2) {
            // 支付宝退款
            $out_trade_no = !empty($shiporder['out_trade_no']) ? $shiporder['out_trade_no'] : trim($shiporder['shiporder_id']);
            $out_request_no = trim($shiporder['shiporder_id']);

            $params = [
                'out_trade_no' => $out_trade_no,
                'refund_amount' => $refund_money,
                'refund_reason' => '出票失败自动退款',
                'out_request_no' => $out_request_no
            ];

            $result = PayApiService::aliRefund($params);

            if (isset($result['code']) && $result['code'] == '10000') {
                // 退款成功
                $this->updateRefundStatus($shiporder, $result['trade_no'] ?? '', $result['refund_fee'] ?? $refund_money, $result);
            } else {
                // 退款失败，记录响应信息
                $this->recordRefundFailure($shiporder, $result);
            }
        }
    }

    /**
     * 更新退款状态
     * @param array $shiporder 船票订单数据
     * @param string $selft_refund_no 退款单号
     * @param float $refund_money 退款金额
     * @param array $result 退款结果
     */
    protected function updateRefundStatus(array $shiporder, string $selft_refund_no, float $refund_money, $result)
    {
        // 更新船票订单
        Db::name('ship_order')
            ->where('id', $shiporder['id'])
            ->update([
                'refund_time' => time(),
                'refund_money' => $refund_money,
                'selft_refund_no' => $selft_refund_no,
                'status' => 5, // 已退款状态
                'refund_response' => json_encode($result),
            ]);

        // 更新关联的商品订单
        $goodsOrder = Db::name('order')->where('orderable_id', $shiporder['id'])->find();
        if ($goodsOrder) {
            Db::name('order')
                ->where('id', $goodsOrder['id'])
                ->update([
                    'refund_time' => time(),
                    'refund_money' => $refund_money,
                    'selft_refund_no' => $selft_refund_no,
                    'status' => 5, // 已退款状态
                    'refund_response' => json_encode($result),
                ]);
        }

        Log::info('船票订单自动退款成功: ' . $shiporder['self_order_no']);
    }

    /**
     * 记录退款失败信息
     * @param array $shiporder 船票订单数据
     * @param array $result 退款结果
     */
    protected function recordRefundFailure(array $shiporder, $result)
    {
        // 记录退款失败响应
        Db::name('ship_order')
            ->where('id', $shiporder['id'])
            ->update([
                'refund_response' => json_encode($result),
            ]);

        // 更新关联的商品订单
        $goodsOrder = Db::name('order')->where('orderable_id', $shiporder['id'])->find();
        if ($goodsOrder) {
            Db::name('order')
                ->where('id', $goodsOrder['id'])
                ->update([
                    'refund_response' => json_encode($result)
                ]);
        }

        Log::error('船票订单自动退款失败: ' . $shiporder['self_order_no'] . ', 原因: ' . json_encode($result));
    }

    /**
     * 船票退款结果回调处理
     * 用于接收船票退款结果的通知
     * @return Json
     */
    public function refundResultNotify()
    {
        try {
            // 获取回调数据
            $data = Request::param();

            // 记录回调日志
            Log::info('船票退款结果回调通知: ' . json_encode($data));

            // 验证必要参数
            if (!isset($data['OrderNo']) || empty($data['OrderNo']) || !isset($data['RefundStatus'])) {
                Log::error('船票退款回调缺少必要参数');
                return json([
                    'State' => 0,
                    'Message' => '缺少必要参数',
                ]);
            }

            // 获取订单模型
            $shipOrderModel = new ShipOrder();

            // 查询订单
            $shipOrder = $shipOrderModel->where('self_order_no', $data['OrderNo'])->find();

            if (!$shipOrder) {
                Log::error('船票订单不存在: ' . $data['OrderNo']);
                return json([
                    'State' => 0,
                    'Message' => '订单不存在',
                ]);
            }

            // 保存退款结果回调数据
            $updateData = [
                'tc_refund_notify' => json_encode($data),
                'update_time' => time(),
            ];

            // 根据退款状态更新订单
            switch ($data['RefundStatus']) {
                case 'SUCCESS':
                    // 退款成功
                    $updateData['status'] = 6;  // 退款成功状态

                    // 如果回调中包含退款金额，更新退款金额
                    if (isset($data['RefundAmount'])) {
                        $updateData['refund_amount'] = $data['RefundAmount'];
                    }

                    Log::info('船票订单退款成功: ' . $data['OrderNo']);
                    break;
                case 'FAILED':
                    // 退款失败
                    $updateData['status'] = 8;  // 退款失败状态

                    // 记录失败原因
                    if (isset($data['FailReason'])) {
                        $updateData['fail_reason'] = $data['FailReason'];
                    }

                    Log::info('船票订单退款失败: ' . $data['OrderNo']);
                    break;
                case 'PROCESSING':
                    // 退款处理中
                    $updateData['status'] = 7;  // 退款处理中状态
                    Log::info('船票订单退款处理中: ' . $data['OrderNo']);
                    break;
            }

            // 更新订单
            $shipOrderModel->where('id', $shipOrder['id'])->update($updateData);

            // 返回成功响应
            return json([
                'State' => 1,
                'Message' => 'Success',
            ]);
        } catch (\Exception $e) {
            // 记录异常日志
            Log::error('船票退款结果回调处理异常: ' . $e->getMessage());
            return json([
                'State' => 0,
                'Message' => '系统异常',
            ]);
        }
    }

    /**
     * 处理订单状态更新
     * @param array $shipOrder 船票订单数据
     * @param array $data 回调数据
     */
    protected function processOrderStatusUpdate(array $shipOrder, array $data)
    {
        // 检查是否有订单状态变更
        if (isset($data['OrderStatus'])) {
            // 根据实际业务需求处理不同的订单状态
            $statusMap = [
                'CONFIRMED' => 1,    // 已确认
                'TICKETED' => 3,     // 已出票
                'CANCELLED' => 5,    // 已取消
                'REFUNDED' => 6,     // 已退款
                'EXPIRED' => 9,      // 已过期
                // 可以根据实际接口文档添加更多状态映射
            ];

            $orderStatus = $data['OrderStatus'];
            if (isset($statusMap[$orderStatus])) {
                $newStatus = $statusMap[$orderStatus];

                // 更新订单状态
                Db::name('ship_order')
                    ->where('id', $shipOrder['id'])
                    ->update(['status' => $newStatus]);

                Log::info('船票订单状态更新: ' . $data['OrderNo'] . ', 旧状态: ' . $shipOrder['status'] . ', 新状态: ' . $newStatus);
            } else {
                Log::info('船票订单状态更新: ' . $data['OrderNo'] . ', 收到未知状态: ' . $orderStatus);
            }
        }

        // 处理其他可能的订单信息更新
        // 例如：航班信息变更、乘客信息变更等
        if (isset($data['FlightChange'])) {
            // 处理航班变更信息
            Log::info('船票订单航班变更: ' . $data['OrderNo'] . ', 变更信息: ' . json_encode($data['FlightChange']));
            // 这里可以添加航班变更的具体处理逻辑
        }
    }
}
